package com.mrogrape.notepad.ui.library;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;

import com.mrogrape.notepad.common.NotepadUtils;
import com.mrogrape.notepad.common.ViewUtils;
import com.mrogrape.notepad.data.ViewContext;
import com.mrogrape.util.StringUtils;

public class LibraryPanePopupMenuBuilder {

	public LibraryPanePopupMenuBuilder(LibraryPane parent) {

		this.parent = parent;
		this.initialize();
	}

	public void showPopup(Component invoker, int x, int y) {

		if (this.parent.isLocationOnNode(x, y)) {

			int selcnt = this.parent.getSelectionNodeCount();

			// 选择的项目有多个的场合
			if(selcnt > 1){

				this.mutiSelectionMenu.show(invoker, x, y);
				return;
			}

			// 提取基准节点
			Object baseObj = this.parent.getObjectForLocation(x, y);

			// 如果选中的是库
			if (baseObj instanceof Library) {

				this.libMenu.show(invoker, x, y);
			}
			// 如果选中的是导入对象
			else if (baseObj instanceof Inclusion){

				Inclusion inclusion = (Inclusion) baseObj;
				this.imRemoveInclusionMenuItem.setEnabled(this.parent.isRootInclusion(inclusion));

				this.inclusionMenu.show(invoker, x, y);
			}

		}
		else {
			this.rootMenu.show(invoker, x, y);
		}
	}

	private void initialize() {

		this.rootMenu = new JPopupMenu();

		this.rootNewLibraryMenuItem = new JMenuItem(this.newLibraryAction);
		this.rootMenu.add(this.rootNewLibraryMenuItem);

		this.mutiSelectionMenu = new JPopupMenu();

		this.msNewLibraryMenuItem = new JMenuItem(this.newLibraryAction);
		this.mutiSelectionMenu.add(this.msNewLibraryMenuItem);

		this.msRemoveLibraryMenuItem = new JMenuItem(this.removeSelectedLibraryAction);
		this.mutiSelectionMenu.add(this.msRemoveLibraryMenuItem);

		this.buildInclusionNodeMenu();
		this.buildLibraryNodeMenu();
	}

	private void buildLibraryNodeMenu(){

		this.libMenu = new JPopupMenu();

		this.libNewLibraryMenuItem = new JMenuItem(this.newLibraryAction);
		this.libMenu.add(this.libNewLibraryMenuItem);

		this.libRemoveLibraryMenuItem = new JMenuItem(this.removeLibraryAction);
		this.libMenu.add(this.libRemoveLibraryMenuItem);

		this.libMenu.add(new JPopupMenu.Separator());

		this.libIncludeInclusionMenuItem = new JMenuItem(this.includeInclusionAction);
		this.libMenu.add(this.libIncludeInclusionMenuItem);
	}
	
	private void buildInclusionNodeMenu(){
		
		this.inclusionMenu = new JPopupMenu();

		this.imRefreshFileInclusionMenuItem = new JMenuItem(this.refreshFileInclusionAction);
		this.inclusionMenu.add(this.imRefreshFileInclusionMenuItem);

		this.inclusionMenu.add(new JPopupMenu.Separator());
		
		this.imRemoveInclusionMenuItem = new JMenuItem(this.removeInclusionAction);
		this.inclusionMenu.add(this.imRemoveInclusionMenuItem);
		
		this.imOpenFileLocaationMenuItem = new JMenuItem(this.openFileInclusionLocationAction);
		this.inclusionMenu.add(this.imOpenFileLocaationMenuItem);
	}

	private LibraryPane parent;
	private InclusionDialog inclusionDialog;

	private JPopupMenu rootMenu;
	private JMenuItem rootNewLibraryMenuItem;

	private JPopupMenu mutiSelectionMenu;
	private JMenuItem msNewLibraryMenuItem;
	private JMenuItem msRemoveLibraryMenuItem;

	private JPopupMenu libMenu;
	private JMenuItem libNewLibraryMenuItem;
	private JMenuItem libRemoveLibraryMenuItem;
	private JMenuItem libIncludeInclusionMenuItem;

	private JPopupMenu inclusionMenu;
	private JMenuItem imRemoveInclusionMenuItem;
	private JMenuItem imOpenFileLocaationMenuItem;
	private JMenuItem imRefreshFileInclusionMenuItem;

	private AbstractAction newLibraryAction = new NewLibraryAction();

	private AbstractAction removeSelectedLibraryAction = new RemoveSelectedLibraryAction();

	private AbstractAction removeLibraryAction = new RemoveLibraryAction();
	private AbstractAction includeInclusionAction = new IncludeInclusionAction();

	private AbstractAction removeInclusionAction = new RemoveInclusionAction();
	private AbstractAction openFileInclusionLocationAction = new OpenFileInclusionLocationAction();
	private AbstractAction refreshFileInclusionAction = new RefreshFileInclusion();

	/**
	 * 新建一个库。
	 * 
	 * <p>
	 * 共通动作。
	 * 
	 * @author IceSpring
	 * @version 1.0
	 *
	 */
	private class NewLibraryAction extends AbstractAction {

		/** serialVersionUID */
		private static final long serialVersionUID = 1L;

		public NewLibraryAction() {

			super.putValue(Action.NAME, "New Library");
		}

		@Override
		public void actionPerformed(ActionEvent e) {

			String input = ViewUtils.showInputDialog((Component) ViewContext.getMainFrame(), "New Library", "Input the name:");
			if (StringUtils.isEmpty(input)) {
				return;
			}

			Library lib = new Library(input);
			LibraryPanePopupMenuBuilder.this.parent.addLibrary(lib);
		}

	}

	/**
	 * 移除选中节点中全部的库节点。
	 * 
	 * <p>
	 * 多选时动作。
	 * 
	 * @author IceSpring
	 * @version 1.0
	 */
	private class RemoveSelectedLibraryAction extends AbstractAction{

		/** serialVersionUID */
		private static final long serialVersionUID = 1L;

		public RemoveSelectedLibraryAction() {

			super.putValue(Action.NAME, "Remove Selected Library");
		}

		@Override
		public void actionPerformed(ActionEvent e) {

			Library[] libraries = LibraryPanePopupMenuBuilder.this.parent.getSelectedLibraries();
			if(libraries.length != 0){
			
				int result = ViewUtils.showOkCancelDialog(null, "Remove Library", "Sure to remove these " + libraries.length + " libraries?");
				if(result == ViewUtils.OK_OPTION){
					for(Library library : libraries){
						LibraryPanePopupMenuBuilder.this.parent.removeLibrary(library);
					}
				}
			}
		}
	}

	/**
	 * 移除选中节点中全部的库节点。
	 * 
	 * <p>
	 * 选择库时动作。
	 * 
	 * @author IceSpring
	 * @version 1.0
	 */
	private class RemoveLibraryAction extends AbstractAction{

		/** serialVersionUID */
		private static final long serialVersionUID = 1L;

		public RemoveLibraryAction() {

			super.putValue(Action.NAME, "Remove Library");
		}

		@Override
		public void actionPerformed(ActionEvent e) {

			Library library = LibraryPanePopupMenuBuilder.this.parent.getSelectedLibrary();
			if(library != null){
				int result = ViewUtils.showOkCancelDialog(null, "Remove Library", "Sure to remove library " + library.getName()+" ?");
				if(result == ViewUtils.OK_OPTION){
					LibraryPanePopupMenuBuilder.this.parent.removeLibrary(library);
				}
				
			}
		}
	}

	/**
	 * 包含一个对象到库中。
	 * 
	 * @author Ice Spring
	 *
	 */
	private class IncludeInclusionAction extends AbstractAction{

		/** serialVersionUID */
		private static final long serialVersionUID = 1L;

		public IncludeInclusionAction() {

			super.putValue(Action.NAME, "Include Object...");
		}

		@Override
		public void actionPerformed(ActionEvent e) {

			Library library = LibraryPanePopupMenuBuilder.this.parent.getSelectedLibrary();
			if(library == null){
				return;
			}

			if(LibraryPanePopupMenuBuilder.this.inclusionDialog == null){
				LibraryPanePopupMenuBuilder.this.inclusionDialog = new InclusionDialog(JOptionPane.getFrameForComponent(LibraryPanePopupMenuBuilder.this.parent));
			} 

			int opt = LibraryPanePopupMenuBuilder.this.inclusionDialog.showDialog("Include Object...", "", "");
			if(opt == InclusionDialog.APPROVE_OPTION){

				String name = LibraryPanePopupMenuBuilder.this.inclusionDialog.getInclusionName();
				String href = LibraryPanePopupMenuBuilder.this.inclusionDialog.getInclusionLocation();

				Inclusion inclusion = null;
				if(LibraryUtils.isUrlString(href)){
					inclusion = new Inclusion(name, Inclusion.URL, href, true, false);
				}
				else{
					inclusion = new Inclusion(name, Inclusion.FILE, href, true, false);
				}

				if(inclusion != null){
					LibraryPanePopupMenuBuilder.this.parent.includeInclusion(library, inclusion);
				}

			}
		}
	}

	/**
	 * 移除选中节点中全部的库节点。
	 * 
	 * <p>
	 * 选择导入对象时动作。
	 * TODO 考虑多选时情况
	 * 
	 * @author IceSpring
	 * @version 1.0
	 */
	private class RemoveInclusionAction extends AbstractAction{

		/** serialVersionUID */
		private static final long serialVersionUID = 1L;

		public RemoveInclusionAction() {

			super.putValue(Action.NAME, "Remove Object");
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			Inclusion inclusion = LibraryPanePopupMenuBuilder.this.parent.getSelectedInclusion();
			if(inclusion == null){
				return;
			}
			Library library = LibraryPanePopupMenuBuilder.this.parent.getLibraryContainsRootInclusion(inclusion, true);

			int op = ViewUtils.showOkCancelDialog(null, "Confirm", "Sure to remove inclusion '" + inclusion.getName() + "' from library '" + library.getName() + "'?");
			if(op == ViewUtils.OK_OPTION){
				LibraryPanePopupMenuBuilder.this.parent.removeRootInclusionFromLibrary(library, inclusion);
			}
		}
	}
	
	/**
	 * 打开文件所在位置。
	 * 
	 * <p>
	 * 选择导入对象时动作。
	 * 
	 * @author IceSpring
	 * @version 1.0
	 */
	private class OpenFileInclusionLocationAction extends AbstractAction{

		/** serialVersionUID */
		private static final long serialVersionUID = 1L;

		public OpenFileInclusionLocationAction() {

			super.putValue(Action.NAME, "Browse in system explorer.");
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			Inclusion inclusion = LibraryPanePopupMenuBuilder.this.parent.getSelectedInclusion();
			if(inclusion == null){
				return;
			}
			if(LibraryUtils.isFileInclusion(inclusion)){
				
				File file = new File(inclusion.getHref());
				try {
					NotepadUtils.openFileLocation(file);
				} catch (IOException e1) {
					ViewUtils.showErrorMessageDialog(null, e1.getMessage());
				}
			}
		}
	}
	
	/**
	 * 刷新文件导入对象。
	 * 
	 * <p>
	 * 选择导入对象时动作。
	 * 
	 * @author IceSpring
	 * @version 1.0
	 */
	private class RefreshFileInclusion extends AbstractAction{

		/** serialVersionUID */
		private static final long serialVersionUID = 1L;

		public RefreshFileInclusion() {

			super.putValue(Action.NAME, "Refresh");
		}

		@Override
		public void actionPerformed(ActionEvent e) {
			LibraryPanePopupMenuBuilder.this.parent.refreshSelectedFileInclusion();
		}
	}

}
